package AST;

import java.util.List;

import TablaSimbolos.Clase;
import TablaSimbolos.Metodo;
import TablaSimbolos.TS;
import TablaSimbolos.Tipos.Tipo;
import TablaSimbolos.Tipos.TipoClase;
import TablaSimbolos.Tipos.TipoVoid;
import exceptions.SemanticException;
import exceptions.SyntaxError;

public class NodoPrimParentizado extends NodoExpPrimario {
	private NodoExpresion e;
	private Tipo checkret;

	public NodoPrimParentizado(NodoExpresion e, NodoExpPrimario siguiente) {
		super();
		this.e = e;
		checkret = null;
		this.setSiguiente(siguiente);

	}

	@Override
	public Tipo check(Metodo metodoLlamador) throws SemanticException {
		if (checkret != null)
			return checkret;
		Tipo expr = e.check(metodoLlamador);

		if (this.getSiguiente() == null) {
			checkret = expr;
			return checkret;
		}

		if (expr instanceof TipoClase) {

			TipoClase tipoExpresion = (TipoClase) expr;
			Clase c = TS.ts().getClass(tipoExpresion.getToken());

			if (this.getSiguiente() instanceof NodoPrimMetodo) // SI EL
																// SIGUIENTE
																// ENCADENADO
																// ES UN
																// METODO

				if (!c.getMetodos().containsKey(
						((NodoPrimMetodo) this.getSiguiente()).getToken()
								.getLexema())) // SI NO ESTA EN LA CLASE
					throw new SemanticException(
							((NodoPrimMetodo) this.getSiguiente()).getToken()
									.getLine(), " El metodo "
									+ ((NodoPrimMetodo) this.getSiguiente())
											.getToken().getLexema()
									+ " no esta declarado en la clase "
									+ tipoExpresion.toString());

				else { // SI ESTA EN LA CLASE DEBO SEGUIR EL CHEQUEO
					checkret = ((NodoPrimMetodo) this.getSiguiente())
							.check(tipoExpresion);
					return checkret;
				}

			if (this.getSiguiente() instanceof NodoPrimID)
				// SI ES UN ID, TENGO QUE FIJARME SI EXISTE UNA VARIABLE DE
				// INSTANCIA
				if (!c.getAtributosInstancia().containsKey(
						((NodoPrimMetodo) this.getSiguiente()).getToken()
								.getLexema()))
					throw new SemanticException(
							((NodoPrimMetodo) this.getSiguiente()).getToken()
									.getLine(), " La variable "
									+ ((NodoPrimMetodo) this.getSiguiente())
											.getToken().getLexema()
									+ " no esta declarado en la clase  "
									+ tipoExpresion.toString());
				else {
					checkret = ((NodoPrimID) this.getSiguiente())
							.check(tipoExpresion);
					return checkret;
				}

			throw new SemanticException(
					e.getLine(),
					"ERROR Semantico: No se puede encadenar un constructor o una expresion parentizada.");
		} else
			throw new SemanticException(e.getLine(), " Un tipo "
					+ expr.toString() + " no puede ser encadenado ");

	}

	@Override
	public int getLine() {
		return e.getLine();
	}
}